#include "ReferenceItem.h"


#include <QCoreApplication>
#include <QTimer>
#include <QDebug>



namespace
{
QString REF_FIELD_NAME = "ref";

const char* TR_CONTEXT = "ReferenceItem";
const char* INVALID_REFERENCE_TEXT = QT_TRANSLATE_NOOP(TR_CONTEXT,"Invalid Reference");

int INTERNAL_VALUE_ROLE = Qt::UserRole+1;
}


ReferenceItem::ReferenceItem(ValueItem* parent, ValueItem* referenced)
    : ValueItem("Reference", parent)
{
    d = new Data();
    if (referenced && !IS_REFERENCE(referenced))
    {
        d->refItem = referenced;
        d->refName = d->refItem->objectName();
        setCustomData(ValueItem::ValueData, d->refItem->data(ValueItem::ValueData, Qt::EditRole));
        connect(d->refItem.data(), SIGNAL(sigDirty()), this, SLOT(onReferenceItemDirty()));
    }
}


bool ReferenceItem::isValid() const
{
    if (d->refItem.isNull()) return false;
    if (d->refName.isEmpty()) return false;
    if (d->refName != d->refItem->objectName()) return false;

    return true;
}


int ReferenceItem::fieldCount() const
{
    return (ReferenceItem::DataType_LAST - AbstractItem::DataType_FIRST + 1);
}


QString ReferenceItem::fieldName(const int &field) const
{
    switch (field)
    {
    case ReferenceData: return REF_FIELD_NAME;
    case ValueItem::ValueData: return QString();
    default:            return ValueItem::fieldName(field);
    }

    return QString::null;
}


int ReferenceItem::field(const QString &field_name) const
{
    if (field_name.toLower() == REF_FIELD_NAME.toLower())   return ReferenceData;

    return ValueItem::field(field_name);
}


QString ReferenceItem::referencedName() const
{
    return data(ReferenceData).toString();
}


ValueItem* ReferenceItem::referencedItem() const
{
    return d->refItem.data();
}


void ReferenceItem::onRefreshReferenceItem()
{
    if (!d->refItem.isNull())
    {
        disconnect(d->refItem.data(), SIGNAL(sigDirty()), this, SLOT(onReferenceItemDirty()));
    }


    ValueItem* refItem = rootItem()->findChild<ValueItem*>(d->refName);
    if (!refItem || IS_REFERENCE(refItem))
    {
        d->refName = QString::null;
        d->refItem = 0;
        setData(ValueItem::ValueData, QVariant());
        emit sigDirty();
        return;
    }

    if (!parent() || refItem == parent()) return;

    foreach (QObject* obj, parent()->children())
    {
        ReferenceItem* otherRefItem = dynamic_cast<ReferenceItem*>(obj);
        if (!otherRefItem) continue;

        if (otherRefItem->referencedItem() == refItem) return;
    }

    d->refItem = refItem;
    d->refName = refItem->objectName();
    setData(ValueItem::ValueData, d->refItem->data(ValueItem::ValueData, Qt::EditRole));

    connect(d->refItem.data(), SIGNAL(sigDirty()), this, SLOT(onReferenceItemDirty()));
}



void ReferenceItem::onReferenceItemDirty()
{
    if (d->refItem.isNull()) return;

    d->refName = d->refItem->objectName();

    if (d->refItem->data(ValueItem::ValueData, INTERNAL_VALUE_ROLE) == data(ValueItem::ValueData, Qt::EditRole)) return;

    setData(ValueItem::ValueData, d->refItem->data(ValueItem::ValueData, Qt::EditRole));
}



QVariant ReferenceItem::customData(const int &field, int role) const
{
    switch (field)
    {
    case ReferenceData:
        {

            if (role == Qt::EditRole) return d->refName;

            if (role != Qt::DisplayRole)  return QVariant();

            if (!isValid()) return tr("Invalid Reference");

            return d->refItem->name();
        }
    case ValueData:
        {
            if (!isValid()) return QVariant();

            if (INTERNAL_VALUE_ROLE)
            {
                return ValueItem::customData(field, Qt::EditRole);
            }

            if (Qt::DisplayRole)
            {
                return d->refItem->data(ValueItem::ValueData, Qt::DisplayRole);
            }

            return QVariant();
        }
    }

    return QVariant();
}



void ReferenceItem::setCustomData(const int &field, const QVariant &value)
{
    switch (field)
    {
    case ReferenceData:
        if (value.toString() == INVALID_REFERENCE_TEXT) return;
        if (d->refName == value.toString()) return;

        d->refName = value.toString();
        QTimer::singleShot(0, this, SLOT(onRefreshReferenceItem()));
        return;

    case ValueData:
        ValueItem::setCustomData(field, value);
        return;

    default:
        return;
    }


}



